﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Open.Data.Persistence
{
    public abstract class Parameter<T>: Expression, IParameter
    {
        public string Name {get; set;}
        public T Value { get; set; }

        public Parameter(T value)
        {
            Name = "parm";
            Value = value;
        }

        public Parameter(string name, T value)
        {
            Name = name;
            Value = value;
        }

        public Type Type
        {
            get
            {
                return typeof(T);
            }
        }

        public virtual string GetValue()
        {
            return Value.ToString();
        }

        public override IEnumerable<IParameter> GetParameters()
        {
            yield return this;
        }

        public override void AppendHashCode(StringBuilder builder)
        {
            builder.Append(typeof(T).FullName);
            builder.Append(Name);
        }
    }

    public class StringParameter: Parameter<string>
    {
        public int Length { get; set; }

        public StringParameter(string value): base(value)
        {
        }
        public StringParameter(string value, string name): base(value)
        {
            Name = name;
        }
        public StringParameter(string value, string name, int length): base(value)
        {
            Name = name;
            Length = length;
        }
        public override void AppendHashCode(StringBuilder builder)
        {
            builder.Append(typeof(string).FullName);
            builder.Append(Name);
            builder.Append(Length.ToString());
        }
    }

    public class LongParameter : Parameter<long>
    {
        public LongParameter(long value) : base(value) 
        {
        }

        public LongParameter(long value, string name): base(value)
        {
            Name = name;
        }
    }

    public class IntegerParameter : Parameter<int>
    {
        public IntegerParameter(int value): base(value)
        {
        }
        public IntegerParameter(int value, string name): base(value)
        {
            Name = name;
        }
    }

    public class DateTimeParameter : Parameter<DateTime>
    {
        public DateTimeParameter(DateTime value) : base(value) 
        {
        }
        public DateTimeParameter(DateTime value, string name): base(value)
        {
            Name = name;
        }
    }

    public class BooleanParameter : Parameter<bool>
    {
        public BooleanParameter(bool value) : base(value) 
        { 
        }
        public BooleanParameter(bool value, string name): base(value)
        {
            Name = name;
        }
    }

    public class ByteParameter : Parameter<byte>
    {
        public ByteParameter(byte value) : base(value)
        { 
        }
        public ByteParameter(byte value, string name): base(value)
        {
            Name = name;
        }
    }

    public class ShortParameter : Parameter<short>
    {
        public ShortParameter(short value) : base(value)
        { 
        }
        public ShortParameter(short value, string name): base(value)
        {
            Name = name;
        }
    }

    public class DoubleParameter : Parameter<double>
    {
        public DoubleParameter(double value) : base(value)
        { 
        }
        public DoubleParameter(double value, string name): base(value)
        {
            Name = name;
        }
    }

    public class FloatParameter : Parameter<float>
    {
        public FloatParameter(float value) : base(value)
        { 
        }
        public FloatParameter(float value, string name): base(value)
        {
            Name = name;
        }
    }

    public class DecimalParameter : Parameter<decimal>
    {
        public int Precision { get; set; }
        public int Scale { get; set; }

        public DecimalParameter(decimal value): base(value)
        {
            Name = "parmDecimal";
            Precision = 14;
            Scale = 5;
        }
        public DecimalParameter(string name, decimal value): base(value)
        {
            Name = name;
            Precision = 14;
            Scale = 5;
        }
        public DecimalParameter(string name, decimal value, int precision, int scale): base(value)
        {
            Name = name;
            Precision = precision;
            Scale = scale;
        }
    }
}
